package me.sdevil507.systemAssist.systemMessage.service.impl;

import com.google.common.collect.Lists;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import me.sdevil507.supports.jpa.PageParamsDTO;
import me.sdevil507.supports.jpa.SortParamsDTO;
import me.sdevil507.systemAssist.systemMessage.Constant.SystemMessageConstant;
import me.sdevil507.systemAssist.systemMessage.dto.SystemMessageParamsDto;
import me.sdevil507.systemAssist.systemMessage.dto.SystemMessageRelDto;
import me.sdevil507.systemAssist.systemMessage.dto.SystemMessageResultDto;
import me.sdevil507.systemAssist.systemMessage.mapper.SystemMessageTextMapper;
import me.sdevil507.systemAssist.systemMessage.po.*;
import me.sdevil507.systemAssist.systemMessage.repository.SystemMessageReceiverRepository;
import me.sdevil507.systemAssist.systemMessage.repository.SystemMessageRelRepository;
import me.sdevil507.systemAssist.systemMessage.repository.SystemMessageTextRepository;
import me.sdevil507.systemAssist.systemMessage.service.SystemMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SystemMessageServiceImpl implements SystemMessageService {

    @Autowired
    private SystemMessageTextRepository messageTextRepository;
    @Autowired
    private SystemMessageRelRepository messageRelRepository;
    @Autowired
    private SystemMessageReceiverRepository messageReceiverRepository;
    @Autowired
    JPAQueryFactory jpaQueryFactory;

    @Override
    public Page<SystemMessageRelPo> readAllByPage(SystemMessageRelDto searchDto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
//        QSystemOperLogPo qSystemOperLogPo = QSystemOperLogPo.systemOperLogPo;
//
//        // 开启谓语查询条件
        Predicate predicate = null;

//        // 获取查询参数
//        String module = searchParamsDto.getOperModule();
//        if (!StringUtils.isEmpty(module)) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.operModule.eq(module));
//        }
//        String operTerminal = searchParamsDto.getOperTerminal();
//        if (!StringUtils.isEmpty(operTerminal)) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.operTerminal.eq(operTerminal));
//        }
//        String operClassify = searchParamsDto.getOperClassify();
//        if (!StringUtils.isEmpty(operClassify)) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.operClassify.eq(operClassify));
//        }
//        Long operOrgId = searchParamsDto.getOperOrgId();
//        if (operOrgId != null) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.operOrgId.eq(operOrgId));
//        }
//        Date startTime = searchParamsDto.getStartTime();
//        Date endTime = searchParamsDto.getEndTime();
//        if (null != startTime) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.createTime.goe(startTime));
//        }
//        if (null != endTime) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.createTime.loe(endTime));
//        }

        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createTime"), new Sort.Order(Sort.Direction.DESC, "createTime"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);

        return messageRelRepository.findAll(predicate, pageable);
    }

    @Override
    public List<SystemMessageRelPo> readAll(SystemMessageParamsDto searchParamsDto, PageParamsDTO pageDto, SortParamsDTO sortDto) {

//        QSystemOperLogPo qSystemOperLogPo = QSystemOperLogPo.systemOperLogPo;

        // 开启谓语查询条件
        Predicate predicate = null;

        // 获取查询参数pid
//        String module = searchParamsDto.getOperModule();
//        if (!StringUtils.isEmpty(module)) {
//            predicate = ExpressionUtils.and(predicate, qSystemOperLogPo.operModule.eq(module));
//        }

        // 排序
        Sort sort = sortDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createTime"), new Sort.Order(Sort.Direction.DESC, "uploadTime"));
        }
        return Lists.newArrayList(messageRelRepository.findAll(predicate, sort).iterator());
    }

    @Override
    public SystemMessageTextPo addMessageText(Long relationId, String messageTitle, String messageContent) {
        return messageTextRepository.save(new SystemMessageTextPo(messageTitle, messageContent, relationId));
    }

    @Override
    public void addMessageRel(Long messageTextId, Long sendUserId, Long sendDeptId, Long receiveUserId, Long receiveDeptId,
                           String receiveMessageTerminal,
                           Integer messageScope,
                           Integer messageClassify,
                           Integer messageType,
                           Integer messageTextState,
                           Integer sendMessageState,
                           String sendMessageTerminal,
                           String sendMessageModule) {

        SystemMessageRelPo systemMessageRelPo = SystemMessageRelPo.builder()
                .messageTextId(messageTextId)
                .messageTextState(messageTextState)
                .messageScope(messageScope)
                .messageClassify(messageClassify)
                .messageType(messageType)
                .sendMessageTerminal(sendMessageTerminal)
                .sendMessageModule(sendMessageModule)
                .sendMessageState(sendMessageState)
                .sendUserId(sendUserId)
                .sendDeptId(sendDeptId)
                .receiveUserId(receiveUserId)
                .receiveDeptId(receiveDeptId)
                .receiveMessageTerminal(receiveMessageTerminal)
                .build();

        try {
            //保存消息关联关系
            messageRelRepository.save(systemMessageRelPo);
        } catch (Exception e) {
            e.printStackTrace();
            systemMessageRelPo.setSendMessageState(SystemMessageConstant.messageSendState.FAILURE);
            messageRelRepository.save(systemMessageRelPo);
        }
    }

    @Override
    public SystemMessageRelPo readById(Long id) {
        return messageRelRepository.findById(id).orElse(null);
    }

    @Override
    public List<SystemMessageResultDto> getMessageData(String terminal, Long deptId, Long userId) {
        QSystemMessageRelPo qSystemMessageRelPo = QSystemMessageRelPo.systemMessageRelPo;
        QSystemMessageReceiverPo qSystemMessageReceiverPo = QSystemMessageReceiverPo.systemMessageReceiverPo;
        QSystemMessageTextPo qSystemMessageTextPo = QSystemMessageTextPo.systemMessageTextPo;

        Predicate messageReceivePredicate = qSystemMessageReceiverPo.isDel.isFalse();
        if(deptId != null){
            messageReceivePredicate = ExpressionUtils.and(messageReceivePredicate, qSystemMessageReceiverPo.receiveDeptId.eq(deptId));
        }else{
            messageReceivePredicate = ExpressionUtils.and(messageReceivePredicate, qSystemMessageReceiverPo.receiveUserId.eq(userId));
        }
        //查询是否有未接收的消息
        this.getNotReceiverMessageData(messageReceivePredicate, terminal, deptId, userId);

        //查询当前的用户消息列表
        return jpaQueryFactory.select(
                    Projections.constructor(SystemMessageResultDto.class,
                            qSystemMessageTextPo.messageTitle,
                            qSystemMessageTextPo.messageContent,
                            qSystemMessageTextPo.relationId,
                            qSystemMessageTextPo.createTime,
                            qSystemMessageRelPo.id,
                            qSystemMessageRelPo.messageScope,
                            qSystemMessageRelPo.messageClassify,
                            qSystemMessageRelPo.messageType,
                            qSystemMessageReceiverPo.id,
                            qSystemMessageReceiverPo.messageReadState
                    )
                ).from(qSystemMessageReceiverPo)
                .leftJoin(qSystemMessageRelPo).on(qSystemMessageReceiverPo.messageRelId.eq(qSystemMessageRelPo.id))
                .leftJoin(qSystemMessageTextPo).on(qSystemMessageRelPo.messageTextId.eq(qSystemMessageTextPo.id))
                .where(messageReceivePredicate)
                .orderBy(qSystemMessageRelPo.createTime.desc())
                .fetch();
    }

    public void getNotReceiverMessageData(Predicate messageReceivePredicate, String terminal, Long deptId, Long userId){
        QSystemMessageReceiverPo qSystemMessageReceiverPo = QSystemMessageReceiverPo.systemMessageReceiverPo;
        QSystemMessageRelPo qSystemMessageRelPo = QSystemMessageRelPo.systemMessageRelPo;

        //已接收消息
        List<Long> receivedRelIdList = jpaQueryFactory.select(qSystemMessageReceiverPo.messageRelId).from(qSystemMessageReceiverPo).where(messageReceivePredicate).fetch();

        Predicate messageRelPredicate = qSystemMessageRelPo.isDel.isFalse();
        //局部消息
        Predicate predicateOne = qSystemMessageRelPo.messageScope.eq(SystemMessageConstant.messageScope.PART)
                .and(qSystemMessageRelPo.receiveMessageTerminal.eq(terminal));
        if(deptId != null){
            predicateOne = ExpressionUtils.and(predicateOne, qSystemMessageRelPo.receiveDeptId.eq(deptId));
        }else{
            predicateOne = ExpressionUtils.and(predicateOne, qSystemMessageRelPo.receiveUserId.eq(userId));
        }
        //全部消息
        Predicate predicateTwo = qSystemMessageRelPo.messageScope.eq(SystemMessageConstant.messageScope.ALL);
        //合并条件
        predicateOne = ExpressionUtils.or(predicateOne, predicateTwo);
        messageRelPredicate = ExpressionUtils.and(messageRelPredicate, predicateOne);

        //查询是否有未读的
        List<SystemMessageRelPo> relPos = jpaQueryFactory.selectFrom(qSystemMessageRelPo)
                .where(messageRelPredicate)
                .where(qSystemMessageRelPo.id.notIn(receivedRelIdList))
                .fetch();

        if(!CollectionUtils.isEmpty(relPos)){
            List<SystemMessageReceiverPo> newReceiverPos = new ArrayList<>();
            relPos.forEach(systemMessageRelPo -> {
                SystemMessageReceiverPo messageReceiverPo = SystemMessageReceiverPo.builder()
                        .messageRelId(systemMessageRelPo.getId())
                        .receiveUserId(userId)
                        .receiveDeptId(deptId)
                        .messageReadState(SystemMessageConstant.messageReadState.UNREAD)
                        .build();
                newReceiverPos.add(messageReceiverPo);
            });
            messageReceiverRepository.saveAll(newReceiverPos);
        }
    }

    @Override
    public void setReadState(Long id) {
        messageReceiverRepository.updateMessageReadStateById(id);
    }
}
